#include "main.h"
#include <string.h>
#include <stdio.h>

int get_index(char op) {
    switch (op) {
        case '+': return 0;
        case '-': return 1;
        case '*': return 2;
        case '/': return 3;
        case '(': return 4;
        case ')': return 5;
        case '#': return 6;
        default: return -1;
    }
}

char pre_table[7][7] = {
        {'>', '>', '<', '<', '<', '>', '>'},
        {'>', '>', '<', '<', '<', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>'},
        {'<', '<', '<', '<', '<', '=', 'x'},
        {'>', '>', '>', '>', 'x', '>', '>'},
        {'<', '<', '<', '<', '<', 'x', '='}
};

int main() {
    char expr[100];
    printf("shuru:\n");
    scanf("%s", expr);

    int result;
    int statud = evaluate(expr, &result);

    if (statud == 0) {
        printf("jieguo: %d\n");
    }else {
        printf("feifa: \n");
    }
    return 0;
}
int init_stack(Stack *s) {
    *s = (Stack)malloc(sizeof(struct stack));
    if (!*s) return 1;
    (*s)->base = (int *)malloc(STACK_MAX_SIZE * sizeof(int));
    if (!(*s)->base) {
        free(*s);
        return 1;
    }
    (*s)->top = (*s)->base;
    (*s)->number_of_elements = 0;
    return 0;
}

int push(Stack s, char val) {
    if (s->number_of_elements >= STACK_MAX_SIZE) return 1;
    *(s->top++) = val;
    s->number_of_elements++;
    return 0;
}

int pop(Stack s, char *val) {
    if (s->number_of_elements == 0) return 1;
    *val = *(--s->top);
    s->number_of_elements--;
    return 0;
}

int get_top(Stack s, char *val) {
    if (s->number_of_elements == 0) return 1;
    *val = (char)*(s->top - 1);
    return 0;
}

bool is_operator(char c) {
    return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#';
}

bool is_operand(char c) {
    return c >= '0' && c <= '9';
}

int compute(int a, char op, int b, int *res) {
    switch (op) {
        case '+': *res = a + b; break;
        case '-': *res = a - b; break;
        case '*': *res = a * b; break;
        case '/':
            if (b == 0) return 1;
            *res = a / b;
            break;
        default: return 1;
    }

    return 0;
}

int evaluate(char *expr, int *result) {
    if (expr[0] != '#' || expr[strlen(expr)-1] != '#') return 1;

    Stack optr, opnd;
    if (init_stack(&optr) || init_stack(&opnd)) return 1;
    push(optr, '#');

    int i =1;
    while (i < strlen(expr)) {
        char c = expr[i];
        if (c == '#') break;

        if(is_operand(c)) {
            if (push(opnd, c)) return 1;
            i++;
        } else if (is_operator(c)) {
            char top;
            if (get_top(optr, &top)) return 1;

            int si = get_index(top), ci = get_index(c);
            if (si == -1 || ci == -1) return 1;
            char rel = pre_table[si][ci];

            if (rel == 'x') return 1;
            if (rel == '<') {
                if (push(optr, c)) return 1;
                i++;
            }else if (rel == '=') {
                pop(optr, &top);
                i++;
            }else if (rel == '>') {
                char op;
                pop(optr, &op);

                char a_char, b_char;
                if (pop(opnd, &b_char) || pop(opnd, &a_char)) return 1;
                int a = a_char - '0', b = b_char - '0';
                int res_val;
                if (compute(a, op, b, &res_val) || res_val < 0 || res_val >9) return 1;
                char res_char = res_val + '0';
                if (push(opnd, res_char)) return 1;
            }
        } else return 1;
    }

    while (1) {
        char top;
        if (get_top(optr, &top) || top == '#') break;

        char op;
        pop(optr, &op);

        char a_char, b_char;
        if (pop(opnd, &b_char) || pop(opnd, &a_char)) return 1;
        int a = a_char - '0', b = b_char - '0';
        int res_val;
        if (compute(a, op, b, &res_val) || res_val < 0 || res_val >9) return 1;
        char res_char = res_val + '0';
        if (push(opnd, res_char)) return 1;
    }

    if (optr->number_of_elements != 1) return 1;

    char res_char;
    pop(opnd, &res_char);
    *result = res_char - '0';
    return 0;
}